package com.maxbill.hadoop.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;

import java.io.*;
import java.net.URI;

/**
 * @功能 HDFS操作工具类
 * @作者 zuoshuai(MaxBill)
 * @日期 2017/11/16
 * @时间 12:12
 */
public class HdfsUtils {
    private final static String userPath = "/user/Administrator/";
    private final static String hdfsPath = "hdfs://127.0.0.1:10000";

    /**
     * @功能 获取HDFS配置信息
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    private static Configuration getHdfsConfig() {
        Configuration config = new Configuration();
        return config;
    }

    /**
     * @功能 获取FS对象
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    private static FileSystem getFileSystem() throws Exception {
        //客户端去操作hdfs时，是有一个用户身份的,默认情况下，hdfs客户端api会从jvm中获取一个参数来作为自己的用户身份：-DHADOOP_USER_NAME=hadoop
        //FileSystem hdfs = FileSystem.get(getHdfsConfig());
        //也可以在构造客户端fs对象时，通过参数传递进去
        FileSystem hdfs = FileSystem.get(new URI(hdfsPath), getHdfsConfig(), "Administrator");
        return hdfs;
    }

    /**
     * @功能 在HDFS创建文件夹
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void mkdir(String path) throws Exception {
        FileSystem fs = getFileSystem();
        Path srcPath = new Path(path);
        boolean isOk = fs.mkdirs(srcPath);
        if (isOk) {
            System.out.println("create dir success...");
        } else {
            System.out.println("create dir failure...");
        }
        fs.close();
    }

    /**
     * @功能 在HDFS创建文件
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void createFile(String filePath, byte[] files) throws Exception {
        FileSystem fs = getFileSystem();
        //目标路径
        Path path = new Path(filePath);
        //打开一个输出流
        FSDataOutputStream outputStream = fs.create(path);
        outputStream.write(files);
        outputStream.close();
        fs.close();
    }

    /**
     * @功能 读取HDFS文件内容
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void readFile(String filePath) throws Exception {
        FileSystem fs = getFileSystem();
        Path path = new Path(filePath);
        InputStream in = null;
        try {
            in = fs.open(path);
            //复制到标准输出流
            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }

    /**
     * @功能 读取HDFS目录详细信息
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void pathInfo(String filePath) throws Exception {
        FileSystem fs = getFileSystem();
        FileStatus[] listStatus = fs.listStatus(new Path(filePath));
        for (FileStatus fileStatus : listStatus) {
            System.out.println(fileStatus.getPath() + ">>>>>" + fileStatus.toString());
        }
    }

    /**
     * @功能 读取HDFS文件列表
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void listFile(String filePath) throws Exception {
        FileSystem fs = getFileSystem();
        //递归找到所有的文件
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path(filePath), true);
        while (listFiles.hasNext()) {
            LocatedFileStatus next = listFiles.next();
            String name = next.getPath().getName();
            Path path = next.getPath();
            System.out.println(name + "---" + path.toString());
        }
    }

    /**
     * @功能 文件重命名
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void renameFile(String oldName, String newName) throws Exception {
        FileSystem fs = getFileSystem();
        Path oldPath = new Path(oldName);
        Path newPath = new Path(newName);
        boolean isOk = fs.rename(oldPath, newPath);
        if (isOk) {
            System.out.println("rename success...");
        } else {
            System.out.println("rename failure...");
        }
        fs.close();
    }

    /**
     * @功能 删除文件
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void deleteFile(String filePath) throws Exception {
        FileSystem fs = getFileSystem();
        Path path = new Path(filePath);
        boolean isOk = fs.deleteOnExit(path);
        if (isOk) {
            System.out.println("delete success...");
        } else {
            System.out.println("delete failure...");
        }
        fs.close();
    }

    /**
     * @功能 上传文件
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void uploadFile(String fileName, String uplaodPath) throws Exception {
        FileSystem fs = getFileSystem();
        //上传路径
        Path clientPath = new Path(fileName);
        //目标路径
        Path serverPath = new Path(uplaodPath);
        //调用文件系统的文件复制方法,前面参数是指是否删除原文件，true为删除，默认为false
        fs.copyFromLocalFile(false, clientPath, serverPath);
        fs.close();
    }

    /**
     * @功能 下载文件
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void downloadFile(String fileName, String downPath) throws Exception {
        FileSystem fs = getFileSystem();
        fs.copyToLocalFile(new Path(fileName), new Path(downPath));
        fs.close();
    }

    /**
     * @功能 判断文件是否存在
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public boolean existFile(String FileName) throws Exception {
        FileSystem hdfs = getFileSystem();
        Path path = new Path(FileName);
        boolean isExists = hdfs.exists(path);
        return isExists;
    }

    /**
     * @功能 主类测试
     * @作者 zuoshuai(MaxBill)
     * @日期 2017/11/16
     * @时间 12:12
     */
    public static void main(String args[]) throws Exception {
        //测试创建目录
        //mkdir("demo");
        //测试创建文件
        //byte[] files = "hello world".getBytes();
        //createFile(userPath + "demo/maxbill.txt", files);
        //测试读取文件
        //readFile(userPath + "demo/maxbill.txt");
        //读取目录信息
        //pathInfo(userPath);
        //读取目录文件
        //listFile(userPath);
        //测试重命名
        //renameFile(userPath + "demo/maxbill.txt", userPath + "demo/shuai.txt");
        //测试删除文件
        //deleteFile(userPath + "demo/shuai.txt");
        //测试上传文件
        //uploadFile("D:\\hello.txt", userPath + "demo/");
        //测试下载文件
        downloadFile(userPath + "demo/hello.txt", "D:\\");
    }
}
